<?php
use Think\Model;

class BaseModel extends Model
{
    protected $tables;

    public function __construct($name = '', $tablePrefix = '', $connection = '')
    {
        parent::__construct($name, $tablePrefix, $connection);
        $this->tables = $this->Tables_in_boxphp();
        $this->user_id = intval(session("user_id"));
        $this->backUrl = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];


    }

    /***********所有表名******/
    public function Tables_in_boxphp()
    {
        $this->tables = $tables = S("Tables_in_boxphp");
        if ($tables) {
            return $tables;
        } else {
            $sql = "show tables";
            $data = M("system_gennum")->query($sql);
            foreach ($data as $one) {
                $r[] = $one['Tables_in_boxphp'];
            }
            S("Tables_in_boxphp", $r);
            $this->tables = $r;
            return $r;
        }
    }


    public function count()
    {
        $key = md5(json_decode($this->options));
        $count = S($key);
        if (!is_numeric($count)) {
            $this->set_cache("select", $key);
            $count = parent::count();
        }
        return $count;
    }

    /****使用find函数会自动缓存，更新的时候会清除缓存****/
    public function find($id, $reload = 0)
    {
        if ((!$id) && (!$this->options['where'])) return false;
        $cache = C('FIND_CACHE');
        /******不使用缓存***/
        if (!$cache) {
            return parent::find($id);
        }
        /******使用缓存***/
        if ($id) {
            $where = array($this->pk => $id);
        } else {
            $where = $this->options['where'];
        }

        $get_cache_key = $this->get_cache_key($where);    //缓存键值
        $data = S($get_cache_key);                        //获得缓存
        if ($data === false || $reload == 1) {
            $r = parent::find($id);
            $data = $r ? $r : 0;
            if ($data[$this->pk]) {
                S($get_cache_key, $data);
                $this->set_cache($data[$this->pk], $get_cache_key);
            }
        }
        $this->options = array();
        if (!$where[$this->pk] && $data[$this->pk]) {
            $where = array($this->pk => $data[$this->pk]);
            return $this->where($where)->find();
        }

        return $data ? $data : NULL;
    }

    /***********主键加载一个*****/
    public function load($id = "")
    {
        if ($id) {
            unset($this->options['where']);
            $data = $this->find($id);
        }
        return $data;
    }

    /*******根据查询条件生成缓键值******/
    protected function get_cache_key($arr)
    {
        /******** 2、条件是字符串****/
        if ($where = $arr['_string']) {
            $where = str_replace("'", "", $where);
            $where = str_replace("(", "", $where);
            $where = str_replace(")", "", $where);
            $where = explode("and", $where);
            foreach ($where as $k => $one) {
                $row = explode("=", trim($one));
                $options[trim($row[0])] = trim(trim($row[1]), "'");
            }
        }
        /******** 条件是数组****/
        if (!$arr['_string']) {
            $options = $arr;
        }
        ksort($options);
        $this->key_options = $options;
        foreach ($options as $k => $v) {
            $options[$k] = "" . $v;        //全部用字符串类型
        }
        $key = $this->name . "_" . md5(json_encode($options));
        return $key;
    }

    /***这个model里有唯一不重的主建多少缓存键值****/
    public function set_cache($pk, $key)
    {
        $name = $this->name . "_" . $pk;
        if ($key) {
            $data = S($name); //当前表，缓存了多少键值
            $data[$key] = 1;
            S($name, $data);
        } else {
            return S($name);
        }
    }

    /******删除缓存***/
    protected function del_cache($pk, $options)
    {
        $data = $this->set_cache($pk);//主键，缓存了多少键值
        foreach ($data as $key => $v) { //删除查询的缓存
            S($key, NULL);
        }
        $data = $this->set_cache("select");//select，count 缓存了多少键值
        foreach ($data as $key => $v) { //删除查询的缓存
            S($key, NULL);
        }

    }


    /*****添加***/
    public function add($data = '', $options = array(), $replace = false)
    {
        $autopartition = C("autopartition");
        if ($this->pk == "id" && empty($data['id']) && $autopartition == 1) {
            $id = get_id($this->name);
            $data['id'] = $id;
        }
        $r = parent::add($data, $options, $replace);
        if ($r) {
            $this->del_cache($r);//返回主键
        }
        return $r;
    }


    /******删除数之后***/
    protected function _after_delete($data, $options)
    {
        $this->del_cache($data[$this->pk], $options);
    }

    /******插入之后之后***/
    protected function _after_insert($data, $options)
    {
        // $this->find($data[$this->pk]);	//生成缓存
        /*****删除查询的缓存**/
        $this->del_cache($data[$this->pk], $options);
        //S($this->name."_all",NULL);
        // $this->del_cache($data[$this->pk],$options);
    }


    /******更新之后之后***/
    protected function _after_update($data, $options)
    {
        //删除缓存
        $this->del_cache($data[$this->pk], $options);
    }


    /****更新操作***/
    public function save($data = '', $options = array())
    {
        //dump($data);exit();
        if ($this->options['where']) {
            $where = $this->options['where'];
        }
        if ($data[$this->pk]) {
            $where = array($this->pk => $data[$this->pk]);
        }
        if (!$where) {
            throw_exception('更新条件不能为空');
        }
        $items = $this->where($where)->select();
        $count = 0;
        foreach ($items as $one) {
            $data[$this->pk] = $one[$this->pk];
            $r = parent::save($data, $options);
            if ($r) $count++;
        }
        return $count;
    }

    /****更新操作***/
    public function delete($options = array())
    {
        $where = $this->options['where'];
        if (!is_array($options)) {
            $where = array($this->pk => $options);
        }
        if (!$where) {
            throw_exception('删除条件不能为空');
        }
        if (!is_array($options)) {
            $where = array($this->pk => $options);
        }
        $items = $this->where($where)->select();
        $count = 0;
        foreach ($items as $one) {
            $r = parent::delete($one[$this->pk]);
            if ($r) $count++;
        }
        return $count;
    }


    /***********清除缓存*****/
    public function resetTables()
    {
        S("Tables_in_boxphp", NULL);
        $this->Tables_in_boxphp();
    }


    /*********没有关联查询列表********/
    public function get($where = 1, $limit = "", $orderBy = "")
    {
        $where = $where ? $where : 1;
        $orderBy = $orderBy ? $orderBy : " $this->pk desc";
        /************从缓存中取得******/
        if (!$limit) {
            $key = $this->name . md5(json_encode($where) . "_" . $orderBy);
            if ($data = S($key)) {
                return $data;
            }
        }
        /******有limit是要分页的****/
        if ($limit) {
            $count = $this->where($where)->count();
            $page = setPager($count, $limit);
            $limit = $page['firstRow'] . "," . $page['listRows'];
        }
        $data = $this->where($where)->field($this->pk)->limit($limit)->order($orderBy)->select();
        if ($data) {
            foreach ($data as $one) {
                $re[] = $this->load($one[$this->pk]);
            }
        }
        if ($data) {
            if ($limit) {
                $data = array(
                    'count' => $count,
                    'list' => $re,
                    'pager' => $page,
                );
            } else {
                $data = $re;
            }
        }
        //当查找全部的时候就缓存起来
        if (!$limit) {
            $this->set_cache("select", $key);
            S($key, $data);
        }
        return $data;
    }


    /****ByPks***/
    public function ByPks($pks)
    {
        $pks = is_array($pks) ? $ids : explode(",", $pks);
        foreach ($pks as $pk) {
            $row = $this->load($pk);
            if ($row) {
                $data[] = $row;
            }
        }
        return $data;
    }

    /*****根据字段来查询 tel***/
    public function ByFields($field, $vals)
    {
        $vals = is_array($vals) ? $vals : explode(",", $vals);
        if ($vals[0]) {
            foreach ($vals as $val) {
                $r = $this->where("$field='$val'")->field($this->pk)->find();
                $id = $r[$this->pk];
                $row = $this->load($id);
                if ($row) {
                    $data[] = $row;
                }
            }
        }
        return $data;
    }


    public function ByField($field, $val)
    {
        $data = $this->ByFields($field, $val);
        return $data[0];
    }

    public function getIn($where = "", $field = "", $type = "string", $limit, $order)
    {
        if (!$where) {
            return false;
        }
        $r = array();
        if (!$field) {
            $field = $this->pk;
        }
        $this->where($where)->field($field);
        if ($limit) {
            $this->limit($limit);
        }
        if ($order) {
            $this->order($order);
        }
        $data = $this->select();
        if (!empty($data)) {
            foreach ($data as $one) {
                if (is_numeric($one[$field])) {
                    $r[] = $one[$field];
                } else {
                    $r[] = "'" . $one[$field] . "'";
                }
            }
            if ($type == "string") {
                $r = implode(",", $r);
            }
            return $r;
        } else {
            return false;
        }
    }


}
 